package com.sky.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.IdUtil;
import com.alibaba.fastjson.JSON;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.sky.context.UserHolder;
import com.sky.dto.*;
import com.sky.entity.AddressBook;
import com.sky.entity.OrderDetail;
import com.sky.entity.Orders;
import com.sky.entity.ShoppingCart;
import com.sky.exception.BusinessException;
import com.sky.mapper.OrderDetailMapper;
import com.sky.mapper.OrdersMapper;
import com.sky.mapper.ShoppingCartMapper;
import com.sky.result.PageBean;
import com.sky.service.AddressBookService;
import com.sky.service.OrderService;
import com.sky.service.ShoppingCartService;
import com.sky.vo.OrderPaymentVO;
import com.sky.vo.OrderStatisticsVO;
import com.sky.vo.OrderSubmitVO;
import com.sky.vo.OrderVO;
import com.sky.websocket.WebSocketServer;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
@Transactional
@RequiredArgsConstructor //由lombok提供,替代@Autowired  但是需要使用final修饰注入的属性
public class OrderServiceImpl implements OrderService {

    private final OrdersMapper ordersMapper;

    private final OrderDetailMapper orderDetailMapper;

    private final AddressBookService addressBookService;

    private final ShoppingCartService shoppingCartService;

    private final ShoppingCartMapper shoppingCartMapper;

    private final WebSocketServer webSocketServer;


    @Override
    public OrderSubmitVO save(Orders orders) {
        //1. 根据地址id查询地址信息
        AddressBook addressBook = addressBookService.findById(orders.getAddressBookId());
        if (addressBook == null) {
            throw new BusinessException("请先选择收货地址");
        }

        //2. 根据登录用户id查询目前的购物车
        List<ShoppingCart> shoppingCartList = shoppingCartService.findList();
        if (CollectionUtil.isEmpty(shoppingCartList)) {
            throw new BusinessException("请先选择下单商品");
        }

        System.out.println("====================");

        //3. 保存订单
        //3-1 补齐订单字段
        orders.setNumber(IdUtil.simpleUUID());//订单号: 自己生成,要求唯一(不能大于32位)
        orders.setStatus(1);//订单状态: 1待付款
        orders.setUserId(UserHolder.get());//下单人id
        orders.setOrderTime(LocalDateTime.now());//下单时间
        orders.setPayStatus(0);//支付状态: 未支付
        orders.setPhone(addressBook.getPhone());//收货人手机号
        orders.setAddress(addressBook.getProvinceName() + addressBook.getCityName() + addressBook.getDistrictName() + addressBook.getDetail());//收货地址
        orders.setConsignee(addressBook.getConsignee());

        //3-2 保存到订单表(主键返回)
        ordersMapper.save(orders);

        //4. 保存订单详情
        //4-1 遍历购物车列表,得到每个购物项
        for (ShoppingCart shoppingCart : shoppingCartList) {
            //4-2 购物项--订单详情（忽略id）
            OrderDetail orderDetail = BeanUtil.copyProperties(shoppingCart, OrderDetail.class, "id");
            //4-3 补齐订单id
            orderDetail.setOrderId(orders.getId());
            //4-4 保存订单详情
            orderDetailMapper.save(orderDetail);
        }

        //5. 清空购物车
        shoppingCartService.clean();

        //6. 返回VO
        OrderSubmitVO orderSubmitVO = OrderSubmitVO.builder()
                .id(orders.getId())
                .orderNumber(orders.getNumber())
                .orderTime(orders.getOrderTime())
                .orderAmount(orders.getAmount())
                .build();
        return orderSubmitVO;
    }

    // 订单支付
    public OrderPaymentVO payment(OrdersPaymentDTO ordersPaymentDTO) throws Exception {
        // 1.直接修改订单状态
        Orders ordersDB = ordersMapper.findByNumber(ordersPaymentDTO.getOrderNumber());
        // 根据订单id更新订单的状态、支付方式、支付状态、结账时间
        Orders orders = Orders.builder()
                .id(ordersDB.getId())
                .status(Orders.TO_BE_CONFIRMED)
                .payStatus(Orders.PAID)
                .checkoutTime(LocalDateTime.now())
                .build();

        ordersMapper.update(orders);

        //===================================通知商家: 新订单来了===========================//
        //1. 构建消息对象
        Map<String,Object> map =new HashMap<String,Object>();
        map.put("type",1);
        map.put("orderId",ordersDB.getId());
        map.put("content","订单号：" + ordersPaymentDTO.getOrderNumber());
        //2 对象转JSON
        String json = JSON.toJSONString(map);//阿里的工具包,将对象转成json
        //3. 调用websocket终端,发送消息给浏览器
        webSocketServer.sendToAllClient(json);
        //===================================通知商家: 新订单来了===========================//

        // 2. 返回一个空结果
        return new OrderPaymentVO();
    }

    //历史订单查询->管理端订单查询
    @Override
    public PageBean<OrderVO> findByPage(OrdersPageQueryDTO ordersPageQueryDTO) {
        //1. 开启分页
        PageHelper.startPage(ordersPageQueryDTO.getPage(), ordersPageQueryDTO.getPageSize());
        //2. 执行查询
        List<OrderVO> voList = ordersMapper.findList(ordersPageQueryDTO);
        Page<OrderVO> page = (Page<OrderVO>) voList;
        //3. <================= 为每个订单填充订单详情=========================>
        if (CollectionUtil.isNotEmpty(page.getResult())) {
            for (OrderVO orderVO : page.getResult()) {
                //3-1 调用orderDetailMapper根据订单id查询详情列表
                List<OrderDetail> details = orderDetailMapper.findByOrderId(orderVO.getId());
                //3-2 将detail封装到vo
                orderVO.setOrderDetailList(details);
                //3-3新增订单明细拼接字符串
                StringBuilder sb = new StringBuilder();
                details.stream().forEach(detail -> {
                    sb.append(detail.getName()).append("x").append(detail.getNumber()).append(";");
                });
                orderVO.setOrderDishes(sb.toString());
            }
        }

        //4. 返回结果
        return new PageBean(page.getTotal(), page.getResult());
    }

    @Override
    public OrderVO findById(Long id) {
        //1. 根据订单id从订单表查询订单基本信息
        OrderVO orderVO = ordersMapper.findById(id);
        //2. 根据订单id从订单详情表查询订单详情列表
        List<OrderDetail> orderDetailList = orderDetailMapper.findByOrderId(id);
        //3. 组装返回vo
        orderVO.setOrderDetailList(orderDetailList);
        return orderVO;
    }

    @Override
    public void cancelById(Long id) {
        //1. 根据订单id查询
        OrderVO orderVO = ordersMapper.findById(id);

        //2. 判断订单状态
        if (orderVO.getStatus() > 2) { //3已接单 4派送中 5已完成 6已取消
            throw new BusinessException("订单无法取消,请联系商家");
        }

        //3. 修改订单状态
        //3-1 构建一个修改对象
        Orders ordersUpdate = Orders.builder()
                .id(id)
                .status(6)//已取消
                .cancelReason("用户取消订单")
                .cancelTime(LocalDateTime.now())
                .build();
        //3-2 如果是已支付的订单,需要发起微信退款请求
        if (orderVO.getPayStatus() == 1) {
            try {
                //weChatPayUtil.refund(orderVO.getNumber(), orderVO.getNumber(), new BigDecimal(0.01), new BigDecimal(0.01));
                ordersUpdate.setPayStatus(2);//2退款
            } catch (Exception e) {
                throw new BusinessException("微信退款失败,联系商家");
            }
        }
        //3-3 执行修改
        ordersMapper.update(ordersUpdate);
    }

    @Override
    public void repetitionById(Long id) {
        //1. 清空当前用户目前购物车中的内容
        shoppingCartService.clean();

        //2. 根据订单id查询订单详情列表
        List<OrderDetail> orderDetailList = orderDetailMapper.findByOrderId(id);

        //3. 遍历详情列表
        if (CollectionUtil.isNotEmpty(orderDetailList)) {
            for (OrderDetail orderDetail : orderDetailList) {
                //3-1 每一个订单详情--->购物车1项
                ShoppingCart shoppingCart = BeanUtil.copyProperties(orderDetail, ShoppingCart.class, "id");
                //3-2 补齐参数
                shoppingCart.setUserId(UserHolder.get());
                shoppingCart.setCreateTime(LocalDateTime.now());
                //3-3 保存到购物车表
                shoppingCartMapper.save(shoppingCart);
            }
        }
    }

    //订单数量统计
    @Override
    public OrderStatisticsVO statistics() {
        //查询每个状态的数量
        Integer toBeConfirmed = ordersMapper.countByStatus(2);
        Integer confirmed = ordersMapper.countByStatus(3);
        Integer deliveryInProgress = ordersMapper.countByStatus(4);
        //封装并返回
        return OrderStatisticsVO.builder()
                .deliveryInProgress(deliveryInProgress)
                .toBeConfirmed(toBeConfirmed)
                .confirmed(confirmed)
                .build();
    }

    /*
    业务规则: 只有订单处于`待接单`状态时可以执行接单操作
    *  商家接单其实就是将订单的状态修改为`已接单`，使用OrdersConfirmDTO接收参数
    */
    @Override//接单
    public void confirm(OrdersConfirmDTO dto) {
        //只有订单处于`待接单`状态时可以执行接单操作
        //查询订单信息,判断状态
        OrderVO vo = ordersMapper.findById(dto.getId());
        if (vo.getStatus() != 2) {
            throw new BusinessException("订单状态不正确,无法接单");
        }
        Orders orders = Orders.builder()
                .id(dto.getId())//根据id修改所以加上id
                .status(3)//已接单
                .build();
        ordersMapper.update(orders);
    }

    /*
      业务规则：
      - 商家拒单时需要指定拒单原因，使用OrdersRejectionDTO接收
      - 只有订单处于`待接单`状态时可以执行拒单操作
      - 商家拒单时，如果用户已经完成了支付，需要为用户退款
      - 商家拒单其实就是将订单状态修改为`已取消`，记录拒单原因、拒单时间
     */
    //拒单
    @Override
    public void rejection(OrdersRejectionDTO dto) {
        //查询订单信息,判断状态
        OrderVO vo = ordersMapper.findById(dto.getId());
        if (vo.getStatus() != 2) {
            throw new BusinessException("订单状态不正确,无法拒单");
        }
        Orders orders = Orders.builder()
                .id(dto.getId())//根据id修改所以加上id
                .status(6)//已取消
                .cancelReason(dto.getRejectionReason())
                .cancelTime(LocalDateTime.now())
                .build();
        ordersMapper.update(orders);
        //如果订单已经支付,需要为用户退款
        if (vo.getPayStatus() == 1) {
            try {
                //调用微信退款
                //weChatPayUtil.refund(vo.getNumber(), vo.getNumber(), new BigDecimal(0.01), new BigDecimal(0.01));
                orders.setPayStatus(2);
                ordersMapper.update(orders);
            } catch (Exception e) {
                throw new BusinessException("微信退款失败,联系商家");
            }
        }
    }

    //取消订单
    /*业务规则：
    - 商家取消订单时需要指定取消原因，使用OrdersCancelDTO接收
    - 只有订单处于`1待付款 2待接单 3已接单 4派送中 `状态时可以执行取消订单操作
    - 取消订单其实就是将订单状态修改为`已取消`
    - 商家取消订单时，如果用户已经完成了支付，需要为用户退款
    */
    @Override
    public void cancel(OrdersCancelDTO dto) {
        //查询订单信息,判断状态
        OrderVO vo = ordersMapper.findById(dto.getId());
        if (vo.getStatus() != 1 && vo.getStatus() != 2 && vo.getStatus() != 3 && vo.getStatus() != 4) {
            throw new BusinessException("订单状态不正确,无法取消");
        }
        Orders orders = Orders.builder()
                .id(dto.getId())//根据id修改所以加上id
                .status(6)//已取消
                .cancelReason(dto.getCancelReason())
                .cancelTime(LocalDateTime.now())
                .build();
        ordersMapper.update(orders);
        //如果订单已经支付,需要为用户退款
        if (vo.getPayStatus() == 1) {
            try {
                //调用微信退款
                //weChatPayUtil.refund(vo.getNumber(), vo.getNumber(), new BigDecimal(0.01), new BigDecimal(0.01));
                orders.setPayStatus(2);
                ordersMapper.update(orders);
            } catch (Exception e) {
                throw new BusinessException("微信退款失败,联系商家");
            }
        }

    }

    //派送订单
    /*业务规则：
-    只有状态为`待派送`的订单可以执行派送订单操作
-     派送订单其实就是将订单状态修改为`派送中`*/
    @Override
    public void delivery(Long id) {
        //1.只有状态为`待派送`的订单可以执行派送订单操作
        OrderVO vo = ordersMapper.findById(id);
        if (vo.getStatus() != 3) {
            throw new BusinessException("订单状态不正确,无法派送");
        }
        Orders orders = Orders.builder()
                .id(id)//根据id修改所以加上id
                .status(4)//派送中
                .build();
        ordersMapper.update(orders);
    }

    //完成订单
    /*
      业务规则：
      - 只有状态为`派送中`的订单可以执行订单完成操作
      - 完成订单其实就是将订单状态修改为`已完成`，订单完成时间为当前时间
      @param id
     */
    @Override
    public void complete(Long id) {
        //1.只有状态为`派送中`的订单可以执行订单完成操作
        OrderVO vo = ordersMapper.findById(id);
        if (vo.getStatus() != 4) {
            throw new BusinessException("订单状态不正确,无法完成");
        }
        Orders orders = Orders.builder()
                .id(id)//根据id修改所以加上id
                .status(5)//已完成
                .deliveryTime(LocalDateTime.now())
                .build();
        ordersMapper.update(orders);

    }

    //催单
    @Override
    public void reminderById(Long id) {
        //1. 查询订单
        OrderVO orderVO = ordersMapper.findById(id);
        if (orderVO == null || orderVO.getStatus() != 2){
            throw new BusinessException("状态错误");
        }
        //2. 构建消息对象
        Map<String,Object> map =new HashMap<String,Object>();
        map.put("type",2);
        map.put("orderId",id);
        map.put("content","订单号：" + orderVO.getNumber());
        //3 对象转JSON
        String json = JSON.toJSONString(map);
        //4. 调用websocket终端,发送消息给浏览器
        webSocketServer.sendToAllClient(json);
    }

}